#include "StdAfx.h"
#include <Windows.h>
#include <WinCrypt.h>
#include "hasher.h"

namespace gfutilities{ namespace crypto
{
	using namespace error;
//-------------------------------------------------------------------------------
buffer hasher::sha1( const unsigned char* data, long len )
{
	buffer res(20);
	hash(CALG_SHA1, data, len, res);

	return res;
}
//-------------------------------------------------------------------------------
void hasher::hash( int hash_type, const unsigned char* data, long len, buffer& out_res )
{
	HCRYPTPROV hProv = NULL;
	
	if(!::CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){
		throw error_code(::GetLastError(), L"Failed CryptAcquireContext()");
	}

	HCRYPTHASH hHash = NULL;
	if (!::CryptCreateHash(hProv, hash_type, 0, 0, &hHash))
	{
		::CryptReleaseContext(hProv, 0);
		throw error_code(::GetLastError(), L"Failed CryptCreateHash()");
	}
	
	if (!::CryptHashData(hHash, data, len, 0))
	{
		::CryptReleaseContext(hProv, 0);
		::CryptDestroyHash(hHash);
		throw error_code(::GetLastError(), L"Failed CryptHashData()");
	}

	DWORD reslen = out_res.size;
	if(!::CryptGetHashParam(hHash, HP_HASHVAL, const_cast<unsigned char*>(out_res.data), &reslen, 0))
	{
		::CryptDestroyHash(hHash);
		::CryptReleaseContext(hProv, 0);
		throw error_code(::GetLastError(), L"Failed CryptGetHashParam()");
	}

	::CryptDestroyHash(hHash);
	::CryptReleaseContext(hProv, 0);
}
//-------------------------------------------------------------------------------
}}